using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Net;
using System.Net.Security;
using System.Reflection;
using System.Security.Cryptography.X509Certificates;
using System.Text;

namespace Lyh.Train.Common.Http
{
    public class HttpClient
    {
        public CookieContainer Cookies = new CookieContainer();
        public string UserAgent = "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.63 Safari/537.36";
        public int TimeOut = 20000;
        public bool AllowAutoRedirect = false;
        public Encoding Encoding = Encoding.UTF8;
        public WebProxy Proxy = null;
        public string ContentType = "application/x-www-form-urlencoded";

        public HttpClient(CookieContainer cookieContainer)
        {
            this.Cookies = cookieContainer;
        }

        public HttpClient()
        {
        }

        private HttpWebResponse GetResponse(string url, string method, string data, string host, string orign, string refer)
        {
            HttpWebResponse httpWebResponse = null;
            try
            {
                NameValueCollection nameValueCollection = new NameValueCollection();
                nameValueCollection.Add("Accept-Encoding", "gzip,deflate,sdch");
                nameValueCollection.Add("Accept-Language", "zh-CN,zh;q=0.8");
                HttpWebRequest httpWebRequest = (HttpWebRequest) WebRequest.Create(url);
                httpWebRequest.KeepAlive = true;
                httpWebRequest.Method = method.ToUpper();
                httpWebRequest.AllowAutoRedirect = true;
                httpWebRequest.CookieContainer = this.Cookies;
                httpWebRequest.ContentType = this.ContentType;
                httpWebRequest.UserAgent = this.UserAgent;
                httpWebRequest.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8";
                httpWebRequest.Timeout = this.TimeOut;
                httpWebRequest.Referer = refer;
                httpWebRequest.Headers.Add(nameValueCollection);
                if (this.Proxy != null)
                {
                    httpWebRequest.Proxy = this.Proxy;
                }
                if (!string.IsNullOrEmpty(host))
                {
                    httpWebRequest.Host = host;
                }
                httpWebRequest.Headers.Add("X-Requested-With", "XMLHttpRequest");
                if (!string.IsNullOrEmpty(orign))
                {
                    httpWebRequest.Headers.Add("Origin", orign);
                }
                if (method.ToUpper() == "POST" && !string.IsNullOrEmpty(data))
                {
                    byte[] bytes = Encoding.GetBytes(data);
                    httpWebRequest.ContentLength = (long) bytes.Length;
                    Stream requestStream = httpWebRequest.GetRequestStream();
                    requestStream.Write(bytes, 0, bytes.Length);
                    requestStream.Close();
                }
                ServicePointManager.ServerCertificateValidationCallback = (RemoteCertificateValidationCallback) Delegate.Combine(ServicePointManager.ServerCertificateValidationCallback, new RemoteCertificateValidationCallback(ValidateServerCertificate));
                if (httpWebRequest.GetResponse() != null)
                {
                    httpWebResponse = (HttpWebResponse) httpWebRequest.GetResponse();
                    if (httpWebResponse.Cookies.Count > 0)
                    {
                        this.Cookies.Add(httpWebResponse.Cookies);
                    }
                }
            }
            catch (WebException ex)
            {
                httpWebResponse = null;
            }
            return httpWebResponse;
        }

        public string Post(string url, string data = "", string host = "", string orign = "", string refer = "", string method = "post")
        {
            return this.GetString(method, url, data, host, orign, refer);
        }

        public string Get(string url, string host = "", string orign = "", string refer = "", string data = "", string method = "get")
        {
            return this.GetString(method, url, data, host, orign, refer);
        }

        private string GetString(string method, string url, string data, string host, string orign, string refer)
        {
            string result = string.Empty;
            HttpWebResponse response = this.GetResponse(url, method, data, host, orign, refer);
            if (response != null)
            {
                Stream stream = response.GetResponseStream();
                if (response.ContentEncoding.ToLower().Contains("gzip"))
                {
                    stream = new GZipStream(stream, CompressionMode.Decompress);
                }
                using (StreamReader streamReader = new StreamReader(stream, this.Encoding))
                {
                    result = streamReader.ReadToEnd();
                }
            }
            return result;
        }

        public Uri GetUri(string url, string method = "get", string data = "", string host = "", string orign = "", string refer = "")
        {
            this.AllowAutoRedirect = false;
            HttpWebResponse response = this.GetResponse(url, method, data, host, orign, refer);
            return response.ResponseUri;
        }

        public byte[] GetImageBytes(string url, string host = "", string orign = "", string refer = "", string data = "", string method = "get")
        {
            HttpWebResponse response = this.GetResponse(url, method, data, host, orign, refer);
            Stream responseStream = response.GetResponseStream();
            MemoryStream memoryStream = new MemoryStream();
            byte[] array = new byte[4096];
            int count;
            while ((count = responseStream.Read(array, 0, array.Length)) > 0)
            {
                memoryStream.Write(array, 0, count);
            }
            return memoryStream.GetBuffer();
        }

        public Stream GetImageStream(string url, string host = "", string orign = "", string refer = "", string data = "", string method = "get")
        {
            HttpWebResponse response = this.GetResponse(url, method, data, host, orign, refer);
            Stream result;
            if (response != null)
            {
                Stream responseStream = response.GetResponseStream();
                result = responseStream;
            }
            else
            {
                result = null;
            }
            return result;
        }

        public bool DownLoad(string url, string fileName, string host = "", string orign = "", string refer = "", string data = "", string method = "get")
        {
            string empty = string.Empty;
            HttpWebResponse response = this.GetResponse(url, method, data, host, orign, refer);
            Stream responseStream = response.GetResponseStream();
            FileStream fileStream = new FileStream(fileName, FileMode.Create);
            int num = 2048;
            byte[] buffer = new byte[num];
            bool result = true;
            try
            {
                for (int i = responseStream.Read(buffer, 0, num); i > 0; i = responseStream.Read(buffer, 0, num))
                {
                    fileStream.Write(buffer, 0, i);
                }
                responseStream.Close();
                fileStream.Close();
                response.Close();
            }
            catch
            {
                result = false;
            }
            return result;
        }

        public string Upload(string url, string fileName, string paramName, string contentType, NameValueCollection nvc, string host = "", string orign = "", string refer = "")
        {
            string str = "---------------------------" + DateTime.Now.Ticks.ToString("x");
            byte[] bytes = Encoding.ASCII.GetBytes("\r\n--" + str + "\r\n");
            HttpWebRequest httpWebRequest = (HttpWebRequest) WebRequest.Create(url);
            httpWebRequest.CookieContainer = this.Cookies;
            httpWebRequest.ContentType = "multipart/form-data; boundary=" + str;
            httpWebRequest.Method = "POST";
            httpWebRequest.KeepAlive = true;
            httpWebRequest.Credentials = CredentialCache.DefaultCredentials;
            Stream requestStream = httpWebRequest.GetRequestStream();
            string format = "Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}";
            foreach (string text in nvc.Keys)
            {
                requestStream.Write(bytes, 0, bytes.Length);
                string s = string.Format(format, text, nvc[text]);
                byte[] bytes2 = Encoding.UTF8.GetBytes(s);
                requestStream.Write(bytes2, 0, bytes2.Length);
            }
            requestStream.Write(bytes, 0, bytes.Length);
            FileInfo fileInfo = new FileInfo(fileName);
            string format2 = "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: {2}\r\n\r\n";
            string s2 = string.Format(format2, paramName, fileInfo.Name, contentType);
            byte[] bytes3 = Encoding.UTF8.GetBytes(s2);
            requestStream.Write(bytes3, 0, bytes3.Length);
            FileStream fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read);
            byte[] array = new byte[4096];
            int count;
            while ((count = fileStream.Read(array, 0, array.Length)) != 0)
            {
                requestStream.Write(array, 0, count);
            }
            fileStream.Close();
            byte[] bytes4 = Encoding.ASCII.GetBytes("\r\n--" + str + "--\r\n");
            requestStream.Write(bytes4, 0, bytes4.Length);
            requestStream.Close();
            WebResponse response = httpWebRequest.GetResponse();
            Stream responseStream = response.GetResponseStream();
            StreamReader streamReader = new StreamReader(responseStream);
            return streamReader.ReadToEnd();
        }

        public string Upload(string url, string fileKeyName, string filePath, NameValueCollection nvc)
        {
            MemoryStream memoryStream = new MemoryStream();
            HttpWebRequest httpWebRequest = (HttpWebRequest) WebRequest.Create(url);
            httpWebRequest.CookieContainer = this.Cookies;
            string str = "---------------" + DateTime.Now.Ticks.ToString("x");
            byte[] bytes = Encoding.ASCII.GetBytes("--" + str + "\r\n");
            FileStream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
            byte[] bytes2 = Encoding.ASCII.GetBytes("--" + str + "--\r\n");
            httpWebRequest.Method = "POST";
            httpWebRequest.Timeout = this.TimeOut;
            httpWebRequest.ContentType = "multipart/form-data; boundary=" + str;
            FileInfo fileInfo = new FileInfo(filePath);
            string s = string.Format("Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: image/jpeg\r\n\r\n", fileKeyName, fileInfo.Name);
            byte[] bytes3 = Encoding.UTF8.GetBytes(s);
            memoryStream.Write(bytes, 0, bytes.Length);
            memoryStream.Write(bytes3, 0, bytes3.Length);
            byte[] array = new byte[1024];
            int count;
            while ((count = fileStream.Read(array, 0, array.Length)) != 0)
            {
                memoryStream.Write(array, 0, count);
            }
            string stringKeyHeader = "\r\n--" + str + "\r\nContent-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}\r\n";
            foreach (byte[] current in 
                from string key in nvc.Keys
                select string.Format(stringKeyHeader, key, nvc[key])
                into formitem
                select Encoding.UTF8.GetBytes(formitem))
            {
                memoryStream.Write(current, 0, current.Length);
            }
            memoryStream.Write(bytes2, 0, bytes2.Length);
            httpWebRequest.ContentLength = memoryStream.Length;
            Stream requestStream = httpWebRequest.GetRequestStream();
            memoryStream.Position = 0L;
            byte[] array2 = new byte[memoryStream.Length];
            memoryStream.Read(array2, 0, array2.Length);
            memoryStream.Close();
            requestStream.Write(array2, 0, array2.Length);
            requestStream.Close();
            HttpWebResponse httpWebResponse = (HttpWebResponse) httpWebRequest.GetResponse();
            string result;
            using (StreamReader streamReader = new StreamReader(httpWebResponse.GetResponseStream(), Encoding.GetEncoding("utf-8")))
            {
                result = streamReader.ReadToEnd();
            }
            fileStream.Close();
            httpWebResponse.Close();
            httpWebRequest.Abort();
            return result;
        }

        public List<Cookie> GetAllCookies()
        {
            CookieContainer cookies = this.Cookies;
            List<Cookie> list = new List<Cookie>();
            Hashtable hashtable = (Hashtable) cookies.GetType().InvokeMember("m_domainTable", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.GetField, null, cookies, new object[0]);
            foreach (object current in hashtable.Values)
            {
                SortedList sortedList = (SortedList) current.GetType().InvokeMember("m_list", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.GetField, null, current, new object[0]);
                foreach (CookieCollection cookieCollection in sortedList.Values)
                {
                    foreach (Cookie item in cookieCollection)
                    {
                        list.Add(item);
                    }
                }
            }
            return list;
        }

        public static bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
        {
            return true;
        }

        public string CreateParameter(IDictionary<string, string> parameters)
        {
            var buffer = new StringBuilder();
            foreach (var key in parameters.Keys)
            {
                buffer.AppendFormat("&{0}={1}", key, parameters[key]);
            }
            return buffer.ToString().TrimStart('&');
        }

    }
}
